#!/bin/sh

#
# Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
#

# TODO gradlew also tries to set ulimit -n (max files), probably we should too
# TODO Script could be run in parallel for the first time, so download/extract code should not fail in that case
# TODO Use slim versions of JetBrains Runtime instead
#  We don't need full JDK here since we don't reuse this runtime for compilation/toolchain

# Possible environment variables:
#   AMPER_DOWNLOAD_ROOT        Maven repository to download Amper dist from.
#                              default: https://packages.jetbrains.team/maven/p/amper/amper
#   AMPER_JRE_DOWNLOAD_ROOT    Url prefix to download Amper JRE from.
#                              default: https:/
#   AMPER_BOOTSTRAP_CACHE_DIR  Cache directory to store extracted JRE and Amper distribution, must end with \
#   AMPER_JAVA_HOME            JRE to run Amper itself (optional, does not affect compilation)

set -e -u

amper_version=0.4.0
amper_url="${AMPER_DOWNLOAD_ROOT:-https://packages.jetbrains.team/maven/p/amper/amper}/org/jetbrains/amper/cli/$amper_version/cli-$amper_version-dist.zip"
amper_jre_download_root="${AMPER_JRE_DOWNLOAD_ROOT:-https:/}"

# Establish chain of trust from here by specifying exact checksum of Amper distribution to be run
amper_sha256=d8286fb1e9bc7b5e771fec08993821ae68cdedb39b8476cee65a5dac1907f6fa

script_dir="$(dirname -- "$0")"
script_dir="$(cd -- "$script_dir" && pwd)"

die () {
  echo >&2
  echo "$@" >&2
  echo >&2
  exit 1
}

download_and_extract() {
  file_url="$1"
  file_sha256="$2"
  cache_dir="$3"
  extract_dir="$4"

  if [ -e "$extract_dir/.flag" ] && [ -n "$(ls "$extract_dir")" ] && [ "x$(cat "$extract_dir/.flag")" = "x${file_url}" ]; then
    # Everything is up-to-date in $extract_dir, do nothing
    true
  else
    mkdir -p "$cache_dir"
    temp_file="$cache_dir/download-file-$$.bin"

    echo "Downloading $file_url"

    rm -f "$temp_file"
    if command -v curl >/dev/null 2>&1; then
      if [ -t 1 ]; then CURL_PROGRESS="--progress-bar"; else CURL_PROGRESS="--silent --show-error"; fi
      # shellcheck disable=SC2086
      curl $CURL_PROGRESS -L --fail --output "${temp_file}" "$file_url" 2>&1
    elif command -v wget >/dev/null 2>&1; then
      if [ -t 1 ]; then WGET_PROGRESS=""; else WGET_PROGRESS="-nv"; fi
      wget $WGET_PROGRESS -O "${temp_file}" "$file_url" 2>&1
    else
      die "ERROR: Please install wget or curl"
    fi

    check_sha256 "$file_url" "$temp_file" "$file_sha256"

    echo "Extracting to $extract_dir"
    rm -rf "$extract_dir"
    mkdir -p "$extract_dir"

    case "$file_url" in
      *".zip") (cd "$extract_dir" && "$AMPER_JAVA_HOME/bin/jar" --extract --file "$temp_file") ;;
      *) tar -x -f "$temp_file" -C "$extract_dir" ;;
    esac

    rm -f "$temp_file"

    echo "$file_url" >"$extract_dir/.flag"
  fi
}

# usage: check_sha256 SOURCE_MONIKER FILE SHA256CHECKSUM
# $1 SOURCE_MONIKER (e.g. url)
# $2 FILE
# $3 SHA256 hex string
check_sha256() {
  if command -v shasum >/dev/null 2>&1; then
    echo "$3 *$2" | shasum -a 256 --status -c || {
      echo "$2 (downloaded from $1):" >&2
      echo "expected checksum $3 but got: $(shasum --binary -a 256 "$2" | awk '{print $1}')" >&2

      die "ERROR: Checksum mismatch for $1"
    }
    return 0
  fi

  if command -v sha256sum >/dev/null 2>&1; then
    echo "$3 *$2" | sha256sum -w -c || {
      echo "$2 (downloaded from $1):" >&2
      echo "expected checksum $3 but got: $(sha256sum "$2" | awk '{print $1}')" >&2

      die "ERROR: Checksum mismatch for $1"
    }
    return 0
  fi

  echo "Both 'shasum' and 'sha256sum' utilities are missing. Please install one of them"
  return 1
}

### System detection
sys=$(uname -s)

if [ "$sys" = "Darwin" ]; then
  amper_cache_dir="${AMPER_BOOTSTRAP_CACHE_DIR:-$HOME/Library/Caches/Amper}"
else
  amper_cache_dir="${AMPER_BOOTSTRAP_CACHE_DIR:-$HOME/.cache/Amper}"
fi

### JVM
# links from https://github.com/corretto/corretto-17/releases
if [ "x${AMPER_JAVA_HOME:-}" = "x" ]; then
  corretto_version=17.0.9.8.1
  jvm_arch=$(uname -m)
  if [ "$sys" = "Darwin" ]; then
    case $jvm_arch in
    x86_64)
      jvm_url="$amper_jre_download_root/corretto.aws/downloads/resources/$corretto_version/amazon-corretto-$corretto_version-macosx-x64.tar.gz"
      jvm_target_dir="$amper_cache_dir/amazon-corretto-$corretto_version-macosx-x64"
      jvm_sha256=7eed832eb25b6bb9fed5172a02931804ed0bf65dc86a2ddc751aa7648bb35c43
      ;;
    arm64)
      jvm_url="$amper_jre_download_root/corretto.aws/downloads/resources/$corretto_version/amazon-corretto-$corretto_version-macosx-aarch64.tar.gz"
      jvm_target_dir="$amper_cache_dir/amazon-corretto-$corretto_version-macosx-aarch64"
      jvm_sha256=8a0c542e78e47cb5de1db40763692d55b977f1d0b31c5f0ebf2dd426fa33a2f4
      ;;
    *)
      die "Unknown architecture $jvm_arch"
      ;;
    esac
  elif [ "$sys" = "cygwin" ] || [ "$sys" = "mingw" ]; then
    # cygwin/mingw should use windows distribution
    die "$sys is not supported yet"
  elif [ "$sys" = "Linux" ]; then
    # shellcheck disable=SC2046
    jvm_arch=$(linux$(getconf LONG_BIT) uname -m)
    case $jvm_arch in
      x86_64)
        jvm_url="$amper_jre_download_root/corretto.aws/downloads/resources/$corretto_version/amazon-corretto-$corretto_version-linux-x64.tar.gz"
        jvm_target_dir="$amper_cache_dir/amazon-corretto-$corretto_version-linux-x64"
        jvm_sha256=0cf11d8e41d7b28a3dbb95cbdd90c398c310a9ea870e5a06dac65a004612aa62
        ;;
      aarch64)
        jvm_url="$amper_jre_download_root/corretto.aws/downloads/resources/$corretto_version/amazon-corretto-$corretto_version-linux-aarch64.tar.gz"
        jvm_target_dir="$amper_cache_dir/amazon-corretto-$corretto_version-linux-aarch64"
        jvm_sha256=8141bc6ea84ce103a040128040c2f527418a6aa3849353dcfa3cf77488524499
        ;;
      *)
        die "Unknown architecture $jvm_arch"
        ;;
    esac
  else
    die "Unsupported platform $sys"
  fi

  download_and_extract "$jvm_url" "$jvm_sha256" "$amper_cache_dir" "$jvm_target_dir"

  AMPER_JAVA_HOME=
  for d in "$jvm_target_dir" "$jvm_target_dir"/* "$jvm_target_dir"/Contents/Home "$jvm_target_dir"/*/Contents/Home; do
    if [ -e "$d/bin/java" ]; then
      AMPER_JAVA_HOME="$d"
    fi
  done

  if [ "x${AMPER_JAVA_HOME:-}" = "x" ]; then
    die "Unable to find bin/java under $jvm_target_dir"
  fi
fi

java_exe="$AMPER_JAVA_HOME/bin/java"
if [ '!' -x "$java_exe" ]; then
  die "Unable to find bin/java executable at $java_exe"
fi

### AMPER
amper_target_dir="$amper_cache_dir/amper-cli-$amper_version"
download_and_extract "$amper_url" "$amper_sha256" "$amper_cache_dir" "$amper_target_dir"

exec "$java_exe" -ea "-Damper.wrapper.dist.sha256=$amper_sha256" "-Damper.wrapper.process.name=$0" -cp "$amper_target_dir/lib/*" org.jetbrains.amper.cli.MainKt "$@"
